package cn.trigram.date;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

/**
 * 时间区间类
 *
 * @version 1.0.0
 * @date 2023/03/07 13:51:05
 * @since 1.0.0
 */
public class DateTimeInterval {

    private final Interval left;
    private final Interval right;

    public DateTimeInterval(Interval left, Interval right) {
        this.left = left;
        this.right = right;
    }

    /**
     * 检查两个时间区间是否有交集
     *
     * @return boolean
     */
    public boolean hasOverlap() {
        // 两个区间没有交集的情况是：一个区间的结束时间在另一个区间的开始时间之前，或者一个区间的开始时间在另一个区间的结束时间之后
        // 因此，只要这两种情况都不成立，就说明两个区间有交集
        return !left.end.isBefore(right.start) && !left.start.isAfter(right.end);
    }


    /**
     * 获取两个时间区间的交集时间范围
     *
     * @return {@link Interval }
     */
    public Interval getIntersection() {
        // 如果两个区间没有交集，返回null
        if (!hasOverlap()) {
            return null;
        }
        // 否则，交集区间的开始时间是两个区间的开始时间中较大的一个，结束时间是两个区间的结束时间中较小的一个
        LocalDateTime start = left.start.isAfter(right.start) ? left.start : right.start;
        LocalDateTime end = left.end.isBefore(right.end) ? left.end : right.end;
        // 返回交集区间
        return new Interval(start, end);
    }

    /**
     * 计算两个时间区间的交集年数
     *
     * @return long
     */
    public long getYearsIntersectionLength() {
        return getIntersectionLength(ChronoUnit.YEARS);
    }

    /**
     * 计算两个时间区间的交集月数
     *
     * @return long
     */
    public long getMonthsIntersectionLength() {
        return getIntersectionLength(ChronoUnit.MONTHS);
    }

    /**
     * 计算两个时间区间的交集天数
     *
     * @return long
     */
    public long getDaysIntersectionLength() {
        return getIntersectionLength(ChronoUnit.DAYS);
    }

    /**
     * 计算两个时间区间的交集小时数
     *
     * @return long
     */
    public long getHoursIntersectionLength() {
        return getIntersectionLength(ChronoUnit.HOURS);
    }

    /**
     * 计算两个时间区间的交集分钟数
     *
     * @return long
     */
    public long getMinutesIntersectionLength() {
        return getIntersectionLength(ChronoUnit.MINUTES);
    }

    /**
     * 计算两个时间区间的交集秒数
     *
     * @return long
     */
    public long getSecondsIntersectionLength() {
        return getIntersectionLength(ChronoUnit.SECONDS);
    }

    /**
     * 计算两个时间区间的交集毫秒数
     *
     * @return long
     */
    public long getMillisIntersectionLength() {
        return getIntersectionLength(ChronoUnit.MILLIS);
    }

    /**
     * 计算两个时间区间的交集指定时间单位的范围长度
     *
     * @return long
     */
    public long getIntersectionLength(ChronoUnit unit) {
        // 如果两个区间没有交集，返回0
        if (!hasOverlap()) {
            return 0;
        }
        // 否则，你可以使用ChronoUnit类来计算两个LocalTime对象之间的时间差，单位可以是秒，分，时等
        // 例如，以下的代码可以计算两个LocalTime对象之间的小时差
        // long hours = ChronoUnit.HOURS.between(time1, time2);
        // 因此，你可以使用以下的代码来计算两个时间区间的交集时间范围的长度，单位是秒
        Interval intersection = getIntersection(); // 获取交集区间
        // 返回交集区间的长度
        return unit.between(intersection.start, intersection.end);
    }

    public static class Interval {
        protected LocalDateTime start; // 区间的开始时间
        protected LocalDateTime end; // 区间的结束时间

        // 构造方法
        public Interval(LocalDateTime start, LocalDateTime end) {
            this.start = start;
            this.end = end;
        }

        public LocalDateTime getStart() {
            return start;
        }

        public LocalDateTime getEnd() {
            return end;
        }
    }
}
